/***************************************************************************
 *   Copyleft 2008-2009 by												   *
 *	 Iwanicki Krzysztof													   *
 *   <gamma.mini.pw.edu.pl/~iwanickik>									   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 ***************************************************************************/
#include "./vVertexBuffer.h"

namespace Vendetta {
	vVertexBuffer::~vVertexBuffer() {
		vDeleteArray(mpVertices);
		vDeleteArray(mpNormals);
		vDeleteArray(mpTexCoords);
		vDeleteArray(mpColors);
	}

	vBool vVertexBuffer::Lock() {
		mLocked = true;

		return true;
	}

	vBool vVertexBuffer::Unlock() {
		mLocked = false;

		return true;
	}

	const vBool vVertexBuffer::IsLocked() const {
		return mLocked;
	}

	vBool vVertexBuffer::SetVertex(vUInt uiInd, vReal x, vReal y, vReal z) {
		if (!mLocked && (mFormat & VVBF_XYZ)) {
			V_CHECK_MSG(uiInd < mVertexCount, "uiInd >= mVertexCount");
			if (!mpVertices) {
				mpVertices = new vPoint3D[mVertexCount];
			}
			mpVertices[uiInd] = vPoint3D(x, y, z);

			return true;
		}
		return false;
	}

	vBool vVertexBuffer::SetVertex(vUInt uiInd, const vPoint3D& vertex) {
		if (!mLocked && (mFormat & VVBF_XYZ)) {
			V_CHECK_MSG(uiInd < mVertexCount, "uiInd >= mVertexCount");
			if (!mpVertices) {
				mpVertices = new vPoint3D[mVertexCount];
			}
			mpVertices[uiInd] = vertex;
			return true;
		}
		return false;
	}

	vBool vVertexBuffer::SetVertices(const vArray<vPoint3D>& vertices) {
		if (!mLocked && !vertices.IsEmpty() && (mFormat & VVBF_XYZ)) {
			vDeleteArray(mpVertices);
			mVertexCount = vertices.Size();
			mpVertices = new vPoint3D[vertices.Size()];
			for (vUInt uiInd = 0; uiInd < vertices.Size(); uiInd++) {
				mpVertices[uiInd] = vertices[uiInd];
			}
			return true;
		}

		return false;
	}

	vBool vVertexBuffer::SetVertices(const vPoint3D* vertices, vUInt vertexCount) {
		if (!mLocked && vertexCount && (mFormat & VVBF_XYZ)) {
			vDeleteArray(mpVertices);
			mVertexCount = vertexCount;
			mpVertices = new vPoint3D[mVertexCount];
			for (vUInt uiInd = 0; uiInd < mVertexCount; uiInd++) {
				mpVertices[uiInd] = vertices[uiInd];
			}
			return true;
		}

		return false;
	}

	vBool vVertexBuffer::SetTexCoord(vUInt uiInd, vReal u, vReal v) {
		if (!mLocked && (mFormat & VVBF_UV)) {
			V_CHECK_MSG(uiInd < mTextCoordCount, "uiInd >= mTexCoordCount");
			if (!mpTexCoords) {
				mpTexCoords = new vPoint2D[mVertexCount];
			}
			mpTexCoords[uiInd] = vPoint2D(u, v);
			return true;
		}

		return false;
	}

	vBool vVertexBuffer::SetTexCoord(vUInt uiInd, const vPoint2D& texCoord) {
		if (!mLocked && (mFormat & VVBF_UV)) {
			V_CHECK_MSG(uiInd < mTextCoordCount, "uiInd >= mTexCoordCount");
			if (!mpTexCoords) {
				mpTexCoords = new vPoint2D[mVertexCount];
			}
			mpTexCoords[uiInd] = texCoord;
			return true;
		}

		return false;
	}

	vBool vVertexBuffer::SetTexCoords(const vArray<vPoint2D>& texCoords) {
		if (!mLocked && !texCoords.IsEmpty() && (mFormat & VVBF_UV)) {
			vDeleteArray(mpTexCoords);
			mTextCoordCount = texCoords.Size();
			mpTexCoords = new vPoint2D[texCoords.Size()];
			for (vUInt uiInd = 0; uiInd < texCoords.Size(); uiInd++) {
				mpTexCoords[uiInd] = texCoords[uiInd];
			}
			return true;
		}

		return false;
	}

	vBool vVertexBuffer::SetTexCoords(const vPoint2D* texCoords, vUInt texCoordCount) {
		if (!mLocked && texCoordCount && (mFormat & VVBF_UV)) {
			vDeleteArray(mpTexCoords);
			mTextCoordCount = texCoordCount;
			mpTexCoords = new vPoint2D[mTextCoordCount];
			for (vUInt uiInd = 0; uiInd < mTextCoordCount; uiInd++) {
				mpTexCoords[uiInd] = texCoords[uiInd];
			}
			return true;
		}

		return false;
	}

	vBool vVertexBuffer::SetNormal(vUInt uiInd, vReal nx, vReal ny, vReal nz) {
		if (!mLocked && (mFormat & VVBF_NXNYNZ)) {
			V_CHECK_MSG(uiInd < mNormalCount, "uiInd >= mNormalCount");
			if (!mpNormals) {
				mpNormals = new vPoint3D[mVertexCount];
			}
			mpNormals[uiInd] = vPoint3D(nx, ny, nz);
			return true;
		}
		return false;
	}

	vBool vVertexBuffer::SetNormal(vUInt uiInd, const vPoint3D& normal) {
		if (!mLocked && (mFormat & VVBF_NXNYNZ)) {
			V_CHECK_MSG(uiInd < mNormalCount, "uiInd >= mNormalCount");
			if (!mpNormals) {
				mpNormals = new vPoint3D[mVertexCount];
			}
			mpNormals[uiInd] = normal;
			return true;
		}
		return false;
	}

	vBool vVertexBuffer::SetNormals(const vArray<vPoint3D>& normals) {
		if (!mLocked && !normals.IsEmpty() && (mFormat & VVBF_NXNYNZ)) {
			vDeleteArray(mpNormals);
			mNormalCount = normals.Size();
			mpNormals = new vPoint3D[normals.Size()];
			for (vUInt uiInd = 0; uiInd < normals.Size(); uiInd++) {
				mpNormals[uiInd] = normals[uiInd];
			}
			return true;
		}
		return false;
	}

	vBool vVertexBuffer::SetNormals(const vPoint3D* normals, vUInt normalCount) {
		if (!mLocked && normalCount && (mFormat & VVBF_NXNYNZ)) {
			vDeleteArray(mpNormals);
			mNormalCount = normalCount;
			mpNormals = new vPoint3D[mNormalCount];
			for (vUInt uiInd = 0; uiInd < mNormalCount; uiInd++) {
				mpNormals[uiInd] = normals[uiInd];
			}
			return true;
		}
		return false;
	}

	vBool vVertexBuffer::SetColor(vUInt uiInd, vReal r, vReal g, vReal b, vReal a) {
		if (!mLocked && (mFormat & VVBF_RGBA)) {
			V_CHECK_MSG(uiInd < mColorCount, "uiInd >= mColorCount");
			if (!mpColors) {
				mpColors = new vColor[mVertexCount];
			}
			mpColors[uiInd] = vColor(r, g, b, a);
			return true;
		}
		return false;
	}

	vBool vVertexBuffer::SetColor(vUInt uiInd, const vColor& color) {
		if (!mLocked && (mFormat & VVBF_RGBA)) {
			V_CHECK_MSG(uiInd < mColorCount, "uiInd >= mColorCount");
			if (!mpColors) {
				mpColors = new vColor[mVertexCount];
			}
			mpColors[uiInd] = color;
			return true;
		}
		return false;
	}

	vBool vVertexBuffer::SetColors(const vArray<vColor>& colors) {
		if (!mLocked && !colors.IsEmpty() && (mFormat & VVBF_RGBA)) {
			vDeleteArray(mpColors);
			mColorCount = colors.Size();
			mpColors = new vColor[colors.Size()];
			for (vUInt uiInd = 0; uiInd < colors.Size(); uiInd++) {
				mpColors[uiInd] = colors[uiInd];
			}
			return true;
		}
		return false;
	}

	vBool vVertexBuffer::SetColors(const vColor* colors, vUInt colorCount) {
		if (!mLocked && colorCount && (mFormat & VVBF_RGBA)) {
			vDeleteArray(mpColors);
			mColorCount = colorCount;
			mpColors = new vColor[mColorCount];
			for (vUInt uiInd = 0; uiInd < mColorCount; uiInd++) {
				mpColors[uiInd] = colors[uiInd];
			}
			return true;
		}
		return false;
	}

	/************************************************************************/
	/* Disabled                                                             */
	/************************************************************************/
	vVertexBuffer::vVertexBuffer() { 
		V_CHECK_MSG(0, "Some tries to call default vVertexBuffer ctor.") ;
	}

	vVertexBuffer::vVertexBuffer(const vVertexBuffer& oGlVertexBuffer) { 
		V_CHECK_MSG(0, "Some tries to call vVertexBuffer copy ctor.") ;
	}

	vVertexBuffer& vVertexBuffer::operator=(const vVertexBuffer& oGlVertexBuffer) { 
		V_CHECK_MSG(0, "Some tries to call vVertexBuffer operator=."); 
		return * this; 
	}
	/************************************************************************/
}